﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;

using System.Linq;
using System.Xml.Linq;

using ProjectBase.Core;
using ProjectBase.Data;
using ProjectBase.Data.Xml;

using $prjsn$.Common;
using $prjsn$.Common.Data.Services;
using $prjsn$.Entity.Services;

namespace $safeprojectname$.Services.Xml
{
    public class ArticleDao : BaseXmlDao<Article, int, ArticleFilter>, IArticleDao
    {
        #region Find

        /// <summary>
        ///     Fills the Criteria list with where statements based on provided filter
        /// </summary>
        /// <param name = "filter"></param>
        /// <returns></returns>
        public override IEnumerable<Article> Find(ArticleFilter filter)
        {
            // Equal
            Criteria.Add(entity => entity.ID.IsEqual(filter.IdExact));
            Criteria.Add(entity => entity.Code.IsExact(filter.CodeExact)); // exact match even for string.Empty

            // Like
            Criteria.Add(entity => entity.Code.IsLike(filter.Code));
            Criteria.Add(entity => entity.Title.IsLike(filter.Title));
            Criteria.Add(entity => entity.Description.IsLike(filter.Description));
            Criteria.Add(entity => entity.Description.IsLike(filter.Text));

            Criteria.Add(
                entity =>
                filter.ArticleCategory.IsNull() || entity.ArticleCategory.Equals(filter.ArticleCategory));
            Criteria.Add(entity => filter.ArticleGroup.IsNull() || entity.ArticleGroup.Equals(filter.ArticleGroup));

            Criteria.Add(
                entity =>
                filter.ArticleCategoryNot.IsNull() || !entity.ArticleCategory.Equals(filter.ArticleCategoryNot));
            Criteria.Add(
                entity =>
                filter.ArticleGroupNot.IsNull() || !entity.ArticleGroup.Equals(filter.ArticleGroupNot));

            Criteria.Add(entity => filter.IsVisible.IsNull() || entity.IsVisible.Equals(filter.IsVisible));

            Criteria.Add(entity => filter.CreatedFrom.IsNull() || entity.CreationDate >= filter.CreatedFrom);
            Criteria.Add(entity => filter.CreatedTo.IsNull() || entity.CreationDate <= filter.CreatedTo);

            Criteria.Add(entity => filter.UpdatedFrom.IsNull() || entity.LastUpdateDate >= filter.UpdatedFrom);
            Criteria.Add(entity => filter.UpdatedTo.IsNull() || entity.LastUpdateDate <= filter.UpdatedTo);

            Criteria.Add(entity => filter.ReleaseFrom.IsNull() || entity.ReleaseDate >= filter.ReleaseFrom);
            Criteria.Add(entity => filter.ReleaseTo.IsNull() || entity.ReleaseDate <= filter.ReleaseTo);

            return GetListByCriteria(filter);
        }

        #endregion Find

        #region XML - ENTITY mapping

        public IArticleCategoryDao ArticleCategoryDao { protected get; set; }
        public IArticleGroupDao ArticleGroupDao { protected get; set; }

        /// <summary>
        ///     Converts the XElement into the Article
        /// </summary>
        /// <param name = "element"></param>
        /// <returns></returns>
        protected override Article CreateEntity(XElement element)
        {
            var entity = FillEntity(new Article(), element); // base converts ValueTypes and String

            if (element.Elements("Text").Count() > 0)
            {
                entity.Text = element.Elements("Text").First().Value;
            }
            if (element.Elements("HtmlText").Count() > 0)
            {
                entity.HtmlText = element.Elements("HtmlText").First().Value;
            }

            entity.ArticleCategory = ArticleCategoryDao.GetById((int)element.Attribute("ArticleCategoryId"));
            entity.ArticleGroup = ArticleGroupDao.GetById((int)element.Attribute("ArticleGroupId"));

            entity.SetId((int)element.Attribute(Str.Common.ID));
            return entity;
        }

        /// <summary>
        ///     Converts the Article instnace into the XElement
        /// </summary>
        /// <param name = "entity"></param>
        /// <returns></returns>
        protected override XElement CreateElement(Article entity)
        {
            var element = base.CreateElement(entity); // base converts ValueTypes and String

            element.Attribute("Text").Remove();
            element.Add(new XElement("Text") { Value = entity.Text });

            element.Attribute("HtmlText").Remove();
            element.Add(new XElement("HtmlText") { Value = entity.HtmlText });

            element.Attribute("ArticleCategoryCode").Remove();
            element.Attribute("ArticleGroupCode").Remove();

            element.Add(new XAttribute("ArticleCategoryId", entity.ArticleCategory.ID));
            element.Add(new XAttribute("ArticleGroupId", entity.ArticleGroup.ID));

            return element;
        }

        #endregion XML - ENTITY mapping

        #region NextId

        /// <summary>
        ///     Incremented 'Next ID' generator.
        ///     Searches for the max existing used value
        ///     and returnes that + 1
        /// </summary>
        /// <returns></returns>
        protected override int GetNextId(Article entity = null)
        {
            var id = 0; // in case there is no element yet
            if (TheList.Any()) // element(s) exist(s) - find the largest ID
            {
                id = TheList.Max<Article, int>(e => e.ID);
            }
            return ++id;
        }

        #endregion NextId
    }
}